import Vue from 'vue'
import Vuex from 'vuex'
import SockJS from 'sockjs-client'
import Stomp from 'stompjs'
import {getToken} from '@/utils/auth'
import core from '@/api/core'
import {sleep} from '@/utils'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    url: '',
    checkInterval: null,//断线重连时 检测连接是否建立成功
    websocket: null,
    stompClient: null,
    listenerList: []//监听器列表，断线重连时 用于重新注册监听
  },
  getters: {
    stompClient(state) {
      return function() {
        return state.stompClient
      }
    }
  },
  mutations: {
    WEBSOCKET_INIT(state, url) {
      if (state.stompClient == null || !state.stompClient.connected) {
        state.url = url
        if(!state.websocket){
          // 没有创建 websocket , 第一次初始化
          this.commit('WEBSOCKET_CONNECT_JUDGE')
          return ;
        }

        if (state.stompClient != null && state.websocket.readyState === SockJS.OPEN) {
          state.stompClient.disconnect(() => {
            this.commit('WEBSOCKET_CONNECT_JUDGE')
          })
        } else if (state.stompClient != null && state.websocket.readyState === SockJS.CONNECTING) {
          console.log('连接正在建立')
          return
        } else {
          this.commit('WEBSOCKET_CONNECT_JUDGE')
        }
        if (!state.checkInterval) {
          state.checkInterval = setInterval(() => {
            console.log('检测连接：' + state.websocket.readyState)
            if (state.stompClient != null && state.stompClient.connected) {
              clearInterval(state.checkInterval)
              state.checkInterval = null
              console.log('重连成功')
            } else if (state.stompClient != null && state.websocket.readyState !== SockJS.CONNECTING) {
              //经常会遇到websocket的状态为open 但是stompClient的状态却是未连接状态，故此处需要把连接断掉 然后重连
              state.stompClient.disconnect(() => {
                this.commit('WEBSOCKET_CONNECT_JUDGE')
              })
            }
          }, 2000)
        }
      } else {
        console.log('websocket 连接已建立成功，不再执行')
      }
    },
    WEBSOCKET_CONNECT_JUDGE(state){
      // 判断是否需要建立连接
      core.hasModule('tools-websocket').then(res => {
        if (res.data){
          this.commit('WEBSOCKET_CONNECT')
        }else{
          console.log('不存在模块 tools-websocket 模块,连接失败')
        }
      })
    },
    WEBSOCKET_CONNECT(state) {
      const _this = this
      const websock = new SockJS(state.url)
      state.websocket = websock
      // 获取STOMP子协议的客户端对象
      const stompClient = Stomp.over(websock)
      stompClient.debug = null //关闭控制台打印
      stompClient.heartbeat.outgoing = 20000
      stompClient.heartbeat.incoming = 0//客户端不从服务端接收心跳包
      // 向服务器发起websocket连接
      let headers = {
        Authorization: getToken()
      }
      stompClient.connect(
        headers,
        frame => {
          console.log('链接成功！')
          state.listenerList.forEach(item => {
            state.stompClient.subscribe(item.topic, item.callback)
          })
          //unsubscribe()可以用来取消客户端对这个目的地destination的订阅
          // stompClient.subscribe("/user/queue/message", msg => {
          //   // this.getData(msg);
          //   console.log(msg)
          // });
        },
        err => {//第一次连接失败和连接后断开连接都会调用这个函数 此处调用重连
          setTimeout(() => {
            _this.commit('WEBSOCKET_INIT', state.url)
          }, 1000)
        }
      )
      state.stompClient = stompClient
    },
    WEBSOCKET_SEND(state, p) {
      if (!state.stompClient){
        console.log('stompClient 为空, 数据发送失败')
        return ;
      }
      let times = 10 ;
      while (state.websocket.readyState === SockJS.CONNECTING && --times > 0){
        console.log('等待次数 ',10 - times)
        sleep(10000);
      }
      state.stompClient.send(p.topic, {
        Authorization: getToken()
      }, p.data)
    },
    WEBSOCKET_SUBSRCIBE(state, p){
      if (!state.stompClient){
        console.log('stompClient 为空, 数据订阅失败')
        return ;
      }
      let times = 10 ;
      while (state.websocket.readyState === SockJS.CONNECTING && --times > 0){
        sleep(100);
      }

      for (let i = 0; i < state.listenerList.length; i++) {
        let listen = state.listenerList[i];
        if (listen.topic === p.topic){
          console.log('指定主题已经被监听:'+p.topic)
          return ;
        }
      }

      state.stompClient.subscribe(p.topic,p.callback,{
        Authorization: getToken()
      });
      state.listenerList.push(p)
    },
    WEBSOCKET_UNSUBSRCIBE(state, p) {
      if (!state.stompClient){
        console.log('stompClient 为空, 数据订阅失败')
        return ;
      }
      let times = 10 ;
      while (state.websocket.readyState === SockJS.CONNECTING && --times > 0){
        sleep(100);
      }

      state.stompClient.unsubscribe(p,{
        Authorization: getToken()
      })
      for (let i = 0; i < state.listenerList.length; i++) {
        if (state.listenerList[i].topic === p) {
          state.listenerList.splice(i, 1)
          console.log('解除订阅：' + p + ' size:' + state.listenerList.length)
          break
        }
      }

    }
  },
  actions: {
    WEBSOCKET_INIT({ commit }, url) {
      commit('WEBSOCKET_INIT', url)
    },
    WEBSOCKET_SEND({ commit }, p) {
      commit('WEBSOCKET_SEND', p)
    },
    WEBSOCKET_UNSUBSRCIBE({ commit }, p) {
      commit('WEBSOCKET_UNSUBSRCIBE', p)
    },
    WEBSOCKET_SUBSRCIBE({ commit }, p){
      commit('WEBSOCKET_SUBSRCIBE', p)
    }
  }
})
